home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 10
/
AACD 10.iso
/
AACD
/
Magazine
/
Online
/
OpenURL
/
Developer
/
Source
/
library_util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-26
|
12KB
|
587 lines
/*
** openurl.library - universal URL display and browser launcher library
** Written by Troels Walsted Hansen <troels@thule.no>
** Placed in the public domain.
**
** Module with utility functions used by the other library functions.
*/
#include "library_common.h"
#include "library_api.h"
#include "library_prefs.h"
#include "library_util.h"
#include "handler.h"
/**************************************************************************
*
* Definitions.
*
*/
#define FINDPORT_NUM 100 /* how many FindPort() to do while waiting */
#define FINDPORT_TIME 10 /* how many seconds to spread those FindPort() over */
struct PlaceHolder
{
char ph_Char;
char *ph_String;
};
/**************************************************************************
*
* Prototypes.
*
*/
static STRPTR ExpandPlaceHolders(STRPTR template, struct PlaceHolder *ph, int num);
static BOOL WriteToFile(STRPTR filename, STRPTR str);
static STRPTR WaitForRexxPort(STRPTR port);
static STRPTR FindRexxPort(struct List *list, STRPTR name);
static BOOL SendRexxMsg(struct MsgPort *replyport, STRPTR rxport, STRPTR rxcmd);
/**************************************************************************
*
* Externally visible functions.
*
*/
BOOL SendToBrowser(STRPTR url, struct List *portlist, struct MsgPort *mp,
BOOL Show, BOOL ToFront, BOOL NewWindow, BOOL Launch)
{
BOOL retval = FALSE;
STRPTR cmd = NULL;
struct PlaceHolder ph[1];
struct URL_BrowserNode *bn;
/* set up the placeholder mapping */
ph[0].ph_Char = 'u'; ph[0].ph_String = url;
/* try to find one of the browsers in the list */
for(bn = (struct URL_BrowserNode *)Prefs->up_BrowserList.mlh_Head;
bn->ubn_Node.mln_Succ;
bn = (struct URL_BrowserNode *)bn->ubn_Node.mln_Succ)
{
STRPTR port = FindRexxPort(portlist, bn->ubn_Port);
if(port)
{
/* send uniconify msg */
if(Show && *bn->ubn_ShowCmd)
SendRexxMsg(mp, port, bn->ubn_ShowCmd);
/* send screentofront command */
if(ToFront && *bn->ubn_ToFrontCmd)
SendRexxMsg(mp, port, bn->ubn_ToFrontCmd);
/* try sending openurl msg */
if(!(cmd = ExpandPlaceHolders(NewWindow ? bn->ubn_OpenURLWCmd : bn->ubn_OpenURLCmd, ph, 1)))
goto done;
if(!(retval = SendRexxMsg(mp, port, cmd)))
{
FreeVec(cmd);
cmd = NULL;
}
else goto done;
}
}
/* no running browser, launch a new one */
if(!Launch) goto done;
for(bn = (struct URL_BrowserNode *)Prefs->up_BrowserList.mlh_Head;
bn->ubn_Node.mln_Succ;
bn = (struct URL_BrowserNode *)bn->ubn_Node.mln_Succ)
{
BOOL startonly;
STRPTR filepart;
char c = '\0';
BPTR lock;
LONG error;
if(!*bn->ubn_Path) continue;
/* compose commandline */
if(strstr(bn->ubn_Path, "%u"))
startonly = TRUE;
else
startonly = FALSE;
if(!(cmd = ExpandPlaceHolders(bn->ubn_Path, ph, 1)))
goto done;
filepart = FilePart(bn->ubn_Path);
if(filepart)
{
c = *filepart;
*filepart = '\0';
}
lock = Lock(bn->ubn_Path, ACCESS_READ);
if(filepart) *filepart = c;
/* start the browser */
error = SystemTags(cmd, SYS_Asynch, TRUE,
SYS_Input, Open("NIL:", MODE_NEWFILE),
SYS_Output, NULL,
lock ? NP_CurrentDir : TAG_IGNORE, lock,
TAG_DONE);
FreeVec(cmd);
cmd = NULL;
if(error)
{
if(lock) UnLock(lock);
continue;
}
if(!startonly)
{
STRPTR rxport;
/* send urlopen command */
if(!(cmd = ExpandPlaceHolders(bn->ubn_OpenURLCmd, ph, 1)))
goto done;
/* wait for the port to appear */
if((rxport = WaitForRexxPort(bn->ubn_Port)))
retval = SendRexxMsg(mp, rxport, cmd);
break;
}
else
{
retval = TRUE;
break;
}
}
done:
if(cmd) FreeVec(cmd);
return(retval);
}
/**************************************************************************/
BOOL SendToMailer(STRPTR url, struct List *portlist, struct MsgPort *mp,
BOOL Show, BOOL ToFront, BOOL Launch)
{
BOOL retval = FALSE, written = FALSE;
struct PlaceHolder ph[5];
STRPTR start, end, address = NULL, subject = NULL, body = NULL, cmd = NULL;
char filename[32];
struct URL_MailerNode *mn;
/* parse the URL "mailto:user@host.domain?subject=Subject?body=Body" */
start = url;
while(start)
{
STRPTR *tag = NULL;
int offset = 1;
if(!strnicmp(start, "mailto:", 7))
{
tag = &address;
offset = 7;
}
else if(!strnicmp(start, "?subject=", 9))
{
tag = &subject;
offset = 9;
}
else if(!strnicmp(start, "?body=", 6))
{
tag = &body;
offset = 6;
}
end = strchr(start + offset, '?');
if(tag && !*tag)
{
if(end) *end = '\0';
if(!(*tag = AllocVec(strlen(start + offset) + 1, MEMF_ANY)))
goto done;
strcpy(*tag, start + offset);
if(end) *end = '?';
}
start = end;
}
if(body)
SPrintf(filename, "T:OpenURL-MailBody.%08lx", FindTask(NULL));
else
{
written = TRUE;
strcpy(filename, "NIL:");
}
/* set up the placeholder mapping */
ph[0].ph_Char = 'a'; ph[0].ph_String = address ? address : (STRPTR)"";
ph[1].ph_Char = 's'; ph[1].ph_String = subject ? subject : url;
ph[2].ph_Char = 'b'; ph[2].ph_String = body ? body : (STRPTR)"";
ph[3].ph_Char = 'f'; ph[3].ph_String = filename;
ph[4].ph_Char = 'u'; ph[4].ph_String = url;
/* try to find one of the mailers in the list */
for(mn = (struct URL_MailerNode *)Prefs->up_MailerList.mlh_Head;
mn->umn_Node.mln_Succ;
mn = (struct URL_MailerNode *)mn->umn_Node.mln_Succ)
{
STRPTR port = FindRexxPort(portlist, mn->umn_Port);
if(port)
{
/* send uniconify msg */
if(Show && *mn->umn_ShowCmd)
SendRexxMsg(mp, port, mn->umn_ShowCmd);
/* send screentofront command */
if(ToFront && *mn->umn_ToFrontCmd)
SendRexxMsg(mp, port, mn->umn_ToFrontCmd);
/* write to temp file */
if(!written && strstr(mn->umn_WriteMailCmd, "%f"))
written = WriteToFile(filename, body);
/* try sending writemail msg */
if(!(cmd = ExpandPlaceHolders(mn->umn_WriteMailCmd, ph, 5)))
goto done;
if(!(retval = SendRexxMsg(mp, port, cmd)))
{
FreeVec(cmd);
cmd = NULL;
}
else goto done;
}
}
/* no running browser, launch a new one */
if(!Launch) goto done;
for(mn = (struct URL_MailerNode *)Prefs->up_MailerList.mlh_Head;
mn->umn_Node.mln_Succ;
mn = (struct URL_MailerNode *)mn->umn_Node.mln_Succ)
{
BOOL startonly;
STRPTR filepart;
char c = '\0';
BPTR lock;
LONG error;
if(!*mn->umn_Path) continue;
/* compose commandline */
if(strstr(mn->umn_Path, "%a"))
startonly = TRUE;
else
startonly = FALSE;
if(!written && strstr(mn->umn_Path, "%f"))
written = WriteToFile(filename, body);
if(!(cmd = ExpandPlaceHolders(mn->umn_Path, ph, 5)))
goto done;
filepart = FilePart(mn->umn_Path);
if(filepart)
{
c = *filepart;
*filepart = '\0';
}
lock = Lock(mn->umn_Path, ACCESS_READ);
if(filepart) *filepart = c;
/* start the mailer */
error = SystemTags(cmd, SYS_Asynch, TRUE,
SYS_Input, Open("NIL:", MODE_NEWFILE),
SYS_Output, NULL,
lock ? NP_CurrentDir : TAG_IGNORE, lock,
TAG_DONE);
FreeVec(cmd);
cmd = NULL;
if(error)
{
if(lock) UnLock(lock);
continue;
}
if(!startonly)
{
STRPTR rxport;
/* send write mail command */
if(!written && strstr(mn->umn_WriteMailCmd, "%f"))
written = WriteToFile(filename, body);
if(!(cmd = ExpandPlaceHolders(mn->umn_WriteMailCmd, ph, 5)))
goto done;
/* wait for the port to appear */
if((rxport = WaitForRexxPort(mn->umn_Port)))
retval = SendRexxMsg(mp, rxport, cmd);
break;
}
else
{
retval = TRUE;
break;
}
}
done:
if(cmd) FreeVec(cmd);
if(body) FreeVec(body);
if(subject) FreeVec(subject);
if(address) FreeVec(address);
return(retval);
}
/**************************************************************************/
BOOL CopyList(struct List *dst, struct List *src, ULONG size)
{
struct Node *n, *new;
/* copy src list into dst, and return success */
for(n = src->lh_Head; n->ln_Succ; n = n->ln_Succ)
{
if(!(new = AllocMem(size, MEMF_ANY)))
{
FreeList(dst, size);
return(FALSE);
}
memcpy(new, n, size);
AddTail(dst, new);
}
return(TRUE);
}
/**************************************************************************/
VOID FreeList(struct List *list, ULONG size)
{
struct Node *n;
while((n = RemHead(list)))
FreeMem(n, size);
}
/**************************************************************************/
BOOL isdigits(STRPTR str)
{
for(;;)
{
if(!*str)
return(TRUE);
else if(!isdigit(*str))
return(FALSE);
str++;
}
}
/**************************************************************************/
VOID SPrintf(STRPTR to, STRPTR fmt, ...)
{
static ULONG fmtfunc = 0x16C04E75;
RawDoFmt(fmt, &fmt + 1, (APTR)&fmtfunc, to);
}
/**************************************************************************
*
* Local functions.
*
*/
static STRPTR ExpandPlaceHolders(STRPTR template, struct PlaceHolder *ph, int num)
{
STRPTR p, result;
int i, length = 0;
/* calculate length of result string */
for(p = template; *p; p++)
{
for(i = 0; i < num; i++)
{
if((*p == '%') && (*(p + 1)== ph[i].ph_Char))
length += strlen(ph[i].ph_String);
}
length++;
}
/* allocate result string */
if(!(result = AllocVec(length + 1, MEMF_PUBLIC)))
return(NULL);
/* perform substitution */
for(p = result; *template; template++)
{
for(i = 0; i < num; i++)
if((*template == '%') && (*(template + 1)== ph[i].ph_Char))
break;
if(i < num)
{
strcpy(p, ph[i].ph_String);
p += strlen(ph[i].ph_String);
template++;
continue;
}
*p++ = *template;
}
*p = '\0';
return(result);
}
/**************************************************************************/
static BOOL WriteToFile(STRPTR filename, STRPTR str)
{
BOOL retval = FALSE;
BPTR fh;
LONG len = strlen(str);
if((fh = Open(filename, MODE_NEWFILE)))
{
if(Write(fh, str, len) == len)
retval = TRUE;
Close(fh);
}
return(retval);
}
/**************************************************************************/
static STRPTR WaitForRexxPort(STRPTR port)
{
LONG i, delay;
/* (busy) wait for the port to appear */
delay = (FINDPORT_TIME * TICKS_PER_SECOND) / FINDPORT_NUM;
for(i = 0; i < FINDPORT_NUM; i++)
{
STRPTR rxport;
Forbid();
rxport = FindRexxPort(&SysBase->PortList, port);
Permit();
if(rxport) return(rxport);
if(SetSignal(0, 0) & SIGBREAKF_CTRL_C)
return(NULL);
Delay(delay);
}
return(NULL);
}
/**************************************************************************/
static STRPTR FindRexxPort(struct List *list, STRPTR name)
{
struct Node *n;
ULONG len;
/* find a rexx port, allowing a .<number> extension */
len = strlen(name);
for(n = list->lh_Head; n->ln_Succ; n = n->ln_Succ)
{
if(n->ln_Name && !strncmp(n->ln_Name, name, len) &&
(n->ln_Name[len] == '\0' ||
(n->ln_Name[len] == '.' && isdigits(&n->ln_Name[len+1]))))
{
return(n->ln_Name);
}
}
return(NULL);
}
/**************************************************************************/
static BOOL SendRexxMsg(struct MsgPort *replyport, STRPTR rxport, STRPTR rxcmd)
{
struct HandlerMsg hm = {0};
hm.hm_Msg.mn_ReplyPort = replyport;
hm.hm_Msg.mn_Length = sizeof(struct HandlerMsg);
hm.hm_Type = HMT_AREXX;
hm.hm_ARexxPort = rxport;
hm.hm_ARexxCmd = rxcmd;
/* check that the handler is still there */
if(!AttemptSemaphore(&HandlerSemaphore))
{
/* yup, still there */
PutMsg(HandlerMsgPort, (struct Message *)&hm);
WaitPort(replyport);
GetMsg(replyport);
return(hm.hm_Success);
}
else
{
/* eek, gone */
ReleaseSemaphore(&HandlerSemaphore);
return(FALSE);
}
}